package com.yu.judge.service.impl;

import cn.hutool.json.JSONUtil;
import com.yu.judge.codesandebox.CodeSandbox;
import com.yu.judge.codesandebox.CodeSandboxProxy;
import com.yu.judge.codesandebox.impl.JavaCodeSandbox_test;
import com.yu.judge.model.ExcuteResponse;
import com.yu.judge.model.ExecuteRequest;
import com.yu.judge.model.JudgeInfo;
import com.yu.judge.service.JudgeService;
import com.yu.judge.service.JudgeService_test;
import com.yu.judge.strategy.JudgeContext;
import com.yu.judge.strategy.strategymanage.StrategyManage;
import com.yu.model.dto.question.JudgeCase;
import com.yu.model.entity.Question;
import com.yu.model.entity.QuestionSubmit;
import com.yu.service.QuestionService;
import com.yu.service.QuestionSubmitService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 判题服务
 * 1）根据题目id获取题目（代码，语言）
 * 2）调用代码沙箱执行代码
 * 3）代码沙箱的返回判断是否正确
 *
 * 测试版1
 * 返回类型为 judginfo  来获取是否答对
 */
@Service
@Slf4j
public class JudgeServiceImpl_test implements JudgeService_test {


    @Resource
    private QuestionService questionService;
    @Resource
    private QuestionSubmitService questionSubmitService;

    @Resource
    private StrategyManage strategyManage;

    @Override
    public JudgeInfo doJudge(Long questionSubmitId) {
        QuestionSubmit questionSubmit = questionSubmitService.getById(questionSubmitId);
        if (questionSubmit == null) {
            throw new RuntimeException();
        }
        Long questionId = questionSubmit.getQuestionId();
        Question question = questionService.getById(questionId);
        if (question == null) {
            throw new RuntimeException("题目为空");
        }
        if (questionSubmit.getStatus() != 0) {
            /**
             * 只有提交为0（等待状态）的时候可以判题
             * 这目前有些问题  本质上想做个状态锁  避免重复提交
             * 应该判题后 不管是否正确都应该重新置为0
             *
             * 上述有不对地方  这个判题状态应该只针对这一个提交记录  下次在提交应该是新的记录 避免重复猛提交 保证一个用户一个题最多保留20条提交记录
             * 实现 查找用户id题目id在提交表中 统计总数 根据创建时间顺序排序删除多余记录
             */
            throw new RuntimeException("状态错误");
        }
        QuestionSubmit questionSubmitUpdate = new QuestionSubmit();
        questionSubmitUpdate.setId(questionSubmitId);
        questionSubmitUpdate.setStatus(1);
        boolean update = questionSubmitService.updateById(questionSubmitUpdate);
        if (!update) {
            throw new RuntimeException("状态错误");
        }

        /**
         * 调用代码沙箱
         */

        String judgeCase = question.getJudgeCase();
        List<JudgeCase> inputList = JSONUtil.toList(judgeCase, JudgeCase.class); //代码用例与答案
        String code = questionSubmit.getCode();
        System.out.println(code);
        List<String> input = inputList.stream().map(JudgeCase::getInput).collect(Collectors.toList());//代码用例
        ExecuteRequest executeRequest = ExecuteRequest.builder()
                .code(code)
                .input(input)
                .language("java")
                .build();

        /**
         * 建立代码沙箱
         */
//        CodeSandbox codeSandbox=new ExampleCodeSandbox();   测试
        CodeSandbox codeSandbox = new JavaCodeSandbox_test();
        CodeSandboxProxy codeSandboxProxy = new CodeSandboxProxy(codeSandbox);
        ExcuteResponse excuteResponse = codeSandboxProxy.excuteCode(executeRequest);

        /**
         * 根据代码沙箱执行结果做出相应判断
         */

        List<String> output = excuteResponse.getOutput();  //执行后的答案
        JudgeInfo judgeInfo = excuteResponse.getJudgeInfo();//执行后的信息

        String message = excuteResponse.getMessage();



        JudgeContext judgeContext = new JudgeContext();
        /**
         * 沙箱执行后的结果
         */
        judgeContext.setOutput(output);
        /**
         * 代码示例
         */
        judgeContext.setInput(input);
        /**
         * 代码判题后的信息
         */
        judgeContext.setJudgeInfo(judgeInfo);
        /**
         *题目
         */
        judgeContext.setQuestion(question);
        /**
         *代码用例与答案
         */
        judgeContext.setInputList(inputList);
        /**
         *
         */
        judgeContext.setQuestionSubmit(questionSubmit);

        judgeContext.setMessage(message);




        JudgeInfo doneJudge = strategyManage.doJudge(judgeContext);


        //根据结果更改数据库信息
        questionSubmitUpdate = new QuestionSubmit();
        questionSubmitUpdate.setId(questionSubmitId);

        if(doneJudge.getSandboxMessage().equals("编译失败")){
            questionSubmitUpdate.setStatus(3);
            questionSubmitUpdate.setJudgeInfo(JSONUtil.toJsonStr(doneJudge));
            boolean updated = questionSubmitService.updateById(questionSubmitUpdate);
            if (!updated) {
                throw new RuntimeException("题目状态更新错误");
            }
            return doneJudge;
        }
        if(doneJudge.getMessage().equals("运行失败")){
            questionSubmitUpdate.setStatus(3);
            questionSubmitUpdate.setJudgeInfo(JSONUtil.toJsonStr(doneJudge));
            boolean updated = questionSubmitService.updateById(questionSubmitUpdate);
            if (!updated) {
                throw new RuntimeException("题目状态更新错误");
            }
        }


        if (doneJudge.getMessage().equals("结果错误")) {
            questionSubmitUpdate.setStatus(3);
        } else {
            questionSubmitUpdate.setStatus(2);
        }
        questionSubmitUpdate.setJudgeInfo(JSONUtil.toJsonStr(doneJudge));
        boolean updated = questionSubmitService.updateById(questionSubmitUpdate);
        if (!updated) {
            throw new RuntimeException("题目状态更新错误");
        }
        QuestionSubmit questionSubmitResult = questionSubmitService.getById(questionSubmitUpdate.getId());

        return doneJudge;
    }
}
